package com.ruoyi.cms.blog.service.impl;

import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.ruoyi.cms.blog.domain.CmsAdvertised;
import com.ruoyi.cms.blog.domain.CmsCity;
import com.ruoyi.cms.blog.domain.CmsMode;
import com.ruoyi.cms.blog.domain.CmsUserAmountLog;
import com.ruoyi.cms.blog.domain.dto.CmsAdvertisedDTO;
import com.ruoyi.cms.blog.domain.vo.CmsAdvertisedVO;
import com.ruoyi.cms.blog.mapper.CmsAdvertisedMapper;
import com.ruoyi.cms.blog.mapper.CmsCityMapper;
import com.ruoyi.cms.blog.mapper.CmsUserAmountLogMapper;
import com.ruoyi.cms.blog.service.ICmsAdvertisedService;
import com.ruoyi.cms.blog.service.ICmsCityService;
import com.ruoyi.cms.blog.service.ICmsModeService;
import com.ruoyi.cms.fileInfo.domain.SysFileInfo;
import com.ruoyi.cms.fileInfo.service.ISysFileInfoService;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class CmsAdvertisedServiceImpl implements ICmsAdvertisedService {
    private final CmsAdvertisedMapper cmsAdvertisedMapper;
    private final ISysFileInfoService iSysFileInfoService;
    private final CmsUserAmountLogMapper cmsUserAmountLogMapper;
    private final RuoYiConfig ruoYiConfig;
    private final ICmsModeService iCmsModeService;
    private final SysUserMapper sysUserMapper;
    private final ISysFileInfoService sysFileInfoService;

    private final CmsCityMapper cmsCityMapper;

    @Override
    public List<CmsAdvertisedVO> list(CmsAdvertisedDTO dto) {
        List<CmsAdvertisedVO> vos = new ArrayList<>(16);
        if (dto.getCategory().equals("4")) {
            dto.setCategory("");
        }
        if (StringUtils.hasText(dto.getCity())) {
            String[] split = dto.getCity().split(",");
            dto.setCity(split[0]);
            dto.setLocation(split[1]);
        }
        Page<CmsAdvertisedVO> objectVOList = new Page<CmsAdvertisedVO>();
        List<CmsAdvertised> list = cmsAdvertisedMapper.list(dto);
        list.forEach(l -> {
            CmsAdvertisedVO vo = new CmsAdvertisedVO();
            BeanUtils.copyProperties(l, vo);
            if (StringUtils.hasText(l.getFileIds())) {
                String s = l.getFileIds().split(",")[0];
                SysFileInfo sysFileInfo = iSysFileInfoService.selectSysFileInfoByFileId(Long.valueOf(s));
                vo.setFileInfos(Collections.singletonList(sysFileInfo));
            }
            String s = Optional.ofNullable(l.getPayment()).orElse("");
            vo.setPayments(s.split(","));
            objectVOList.add(vo);
        });
        objectVOList.setTotal(((Page)list).getTotal());
        return objectVOList;
    }

    @Override
    public AjaxResult topList(CmsAdvertisedDTO dto) {
        return AjaxResult.success(cmsAdvertisedMapper.topList(dto));
    }

    @Override
    public AjaxResult getById(Long id) {
        CmsAdvertised one = cmsAdvertisedMapper.getById(id);
        // 原子性增加
//        long newViews = atomicLong.addAndGet(1);
        // 更新数据库
        // CmsAdvertised ca = new CmsAdvertised();
        one.setViews((one.getViews() == null ? 0 : one.getViews()) + 1);
        cmsAdvertisedMapper.update(one);
        CmsAdvertisedVO vo = new CmsAdvertisedVO();
        BeanUtils.copyProperties(one, vo);
        if (StringUtils.hasText(one.getFileIds())) {
            List<String> list = Arrays.asList(one.getFileIds().split(","));
            List<SysFileInfo> collect = iSysFileInfoService.selectFileByFiledIds(list);
            vo.setFileInfos(collect);
        }
        return AjaxResult.success(vo);
    }

    @Override
    public AjaxResult getUpdateId(Long id) {
        Long userId = SecurityUtils.getUserId();
        CmsAdvertised one = cmsAdvertisedMapper.getById(id);
        if (null == one || !one.getCreateBy().equals(String.valueOf(userId))) {
            return AjaxResult.success("", null);
        } else {
            // 更新数据库
            CmsAdvertised ca = new CmsAdvertised();
            ca.setViews((one.getViews() == null ? 0 : one.getViews()) + 1);
            ca.setUpdateTime(new Date());
            cmsAdvertisedMapper.update(ca);
            CmsAdvertisedVO vo = new CmsAdvertisedVO();
            BeanUtils.copyProperties(one, vo);
            if (StringUtils.hasText(one.getFileIds())) {
                List<String> list = Arrays.asList(one.getFileIds().split(","));
                List<SysFileInfo> collect = iSysFileInfoService.selectFileByFiledIds(list);
                vo.setFileInfos(collect);
            }
            return AjaxResult.success(vo);
        }
    }

    @Override
    public AjaxResult updateTime(Long id) {
        CmsAdvertised one = cmsAdvertisedMapper.getById(id);
        //CmsAdvertised ca = new CmsAdvertised();
        one.setUpdateTime(new Date());
        cmsAdvertisedMapper.update(one);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult test2() {
        CmsCity query = new CmsCity();
        List<CmsCity> citys = cmsCityMapper.select(query);
        Set<String> zhou = new HashSet<>();
        for (CmsCity city : citys) {
            zhou.add(city.getZhouName());
        }
        for (String s : zhou) {
            //File file = new File("C:\\Users\\GengZhuag\\Desktop\\html\\" + s + ".html");
            File file = new File("/root/html/" + s + ".html");

            Document doc = null;
            try {
                doc = Jsoup.parse(file, "utf-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            //System.out.println(doc.html());
            Element elementById = doc.getElementById("city-list");
            Elements elementsByTag = elementById.getElementsByTag("li");
            for (Element element : elementsByTag) {
                String cityName = element.getElementsByTag("a").get(0).text();
                //System.out.println(cityName);
                CmsCity query2 = new CmsCity();
                query2.setName(cityName);
                query2.setZhouName(s);
                List<CmsCity> citysQuery = cmsCityMapper.getOne2(query2);
                if (citysQuery != null && citysQuery.size() <= 0) {
                    // 插入
                    CmsCity insert = new CmsCity();
                    insert.setZhouName(s);
                    insert.setName(cityName);
                    insert.setStatus("0");
                    cmsCityMapper.insert(insert);
                }
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult test(String zhouNameParam) throws Exception {
        String url = "https://bodyrubsmap.com";
        try {
            Document doc = getSSLDoc(url);
            // 获取USA的所有州和城市
            Elements geoUnit = doc.getElementsByClass("united-states").get(0).getElementsByClass("geoUnit");
            // 遍历州
            for (Element zhou : geoUnit) {
                Elements zhouAndCity = zhou.getElementsByTag("a");
                String zhou_name = "";
                for (int i = 0; i < zhouAndCity.size(); i++) {
                    Element eZhouAndCity = zhouAndCity.get(i);
                    if ( i == 0 ) {
                        zhou_name = eZhouAndCity.text();
                    } else if (i != 0 && zhouNameParam.equals(zhou_name)) {
                        String city = eZhouAndCity.text();
                        System.out.println(zhou_name+"_"+city+"_"+eZhouAndCity.attr("href"));
                        disposeUrl(zhou_name, city, eZhouAndCity.attr("href"));
                    }
                }
            }
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            return AjaxResult.success();
        }
    }

    /**
     * 处理城市中的两个类型
     *
     * @param zhouName
     * @param city
     * @param href
     */
    private void disposeUrl(String zhouName, String city, String href) throws Exception {
        String[] split = href.split("/");
        // 获取391.html
        String sPrefix = split[split.length - 1];
        // Body Rub 类型URl
        String urlBodyRub = "/city/" + sPrefix;
        // Escort类型URl
        String urlEscort = "/escort/c/" + sPrefix;
        getBodyRubList(zhouName, city, urlBodyRub);
        getEscortList(zhouName, city, urlEscort);
    }

    /**
     * 处理Escort卡片列表
     * @param zhouName
     * @param city
     * @param urlEscort
     */
    private void getEscortList(String zhouName, String city, String urlEscort) throws Exception {
        String url = "https://bodyrubsmap.com";
        Document sslDoc = null;
        try {
            sslDoc = getSSLDoc(url + urlEscort);
            //System.out.println(sslDoc.html());
            Elements cats = sslDoc.getElementsByClass("ren-col-md3");
            int i = 0;
            for (Element cat : cats) {
                if (i++ >= 3) {
                    break;
                }
                Element detailEle = cat.getElementsByTag("a").get(0);
                String href = detailEle.attr("href");
                Document detailDoc = getSSLDoc(url + href);
                // System.out.println(detailDoc.html());
                insertAd(zhouName, city, "3", detailDoc, zhouName + city + "3" + url + href);
                Thread.sleep(1000L);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 处理BodyRubList 列表
     * @param zhouName
     * @param city
     * @param urlBodyRub
     */
    private void getBodyRubList(String zhouName, String city, String urlBodyRub) {
        String url = "https://bodyrubsmap.com";
        Document sslDoc = null;
        try {
            sslDoc = getSSLDoc(url + urlBodyRub);
            //System.out.println(sslDoc.html());
            Elements cats = sslDoc.getElementsByClass("cat");
            int i = 0;
            for (Element cat : cats) {
                if (i++ >= 3) {
                    break;
                }
                Element detailEle = cat.getElementsByTag("a").get(0);
                String href = detailEle.attr("href");
                Document detailDoc = getSSLDoc(url + href);
                //System.out.println(detailDoc.html());
                insertAd(zhouName, city, "2", detailDoc, zhouName + city + "2" + url + href);
                Thread.sleep(1000L);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析详情，插入广告表和图片表
     *
     * @param zhouName
     * @param city
     * @param category
     * @param detailDoc
     */
    private void insertAd(String zhouName, String city, String category, Document detailDoc, String oriUrl) {
        // 检测上次是否抓取过，如果已抓取直接跳过
        CmsAdvertisedDTO query = new CmsAdvertisedDTO();
        query.setRemark(oriUrl);
        List<CmsAdvertised> list = cmsAdvertisedMapper.list(query);
        if (list != null && list.size() > 0) {
            System.out.println("跳过抓取执行时长：0 毫秒");
            return ;
        }
        Long start = System.currentTimeMillis();
        String url = "https://bodyrubsmap.com";
        String filePath = RuoYiConfig.getUploadPath();
        // 1.标题
        String title = "";
        Random r = new Random();
        Integer age = 20 + (r.nextInt(11));
        // 2.电话
        String phone = "";
        // 3.地址
        String address = "";
        // 4.详情
        String des = "";
        Long views = Long.valueOf(r.nextInt(50));
        // 5.图片
        String fileIds = "";

        // 核心处理逻辑，获取5个内容
        title = detailDoc.getElementById("postingTitle").getElementsByTag("h1").get(0).text();
        if (detailDoc.getElementsByClass("bot_tel_btn") != null
        && detailDoc.getElementsByClass("bot_tel_btn").size() > 0) {
            phone = detailDoc.getElementsByClass("bot_tel_btn").get(0).text();
        }

        des = detailDoc.getElementsByClass("postingBody").get(0).html();

        Elements imgs = detailDoc.getElementById("viewAdPhotoLayout").getElementsByTag("img");
        for (Element img : imgs) {
            String src = url + img.attr("src");
            String[] srcSplit = src.split("/");
            String originalFilename = srcSplit[srcSplit.length - 1];
            String extension = src.substring(src.lastIndexOf(".") + 1);
            String fileObjectName = IdUtils.fastUUID() + "." + extension;
            String fileName = DateUtils.datePath() + File.separator + fileObjectName;
            String dest = filePath + File.separator + fileName;
            String destPath = filePath + File.separator + DateUtils.datePath();
            File dir = new File(destPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            try {
                FileUploadUtils.downloadImage(src, dest);
                // 下载成功，存储原始数据
                SysFileInfo sysFileInfo = new SysFileInfo();

                // 计算文件大小信息
                long size = FileUploadUtils.getFileSize(dest);
                String fileSizeInfo = "0kB";
                if (size!=0){
                    String[] unitNames = new String[]{"B", "kB", "MB", "GB", "TB", "EB"};
                    int digitGroups = Math.min(unitNames.length-1, (int) (Math.log10(size) / Math.log10(1024)));
                    fileSizeInfo = new DecimalFormat("#,##0.##").format(size / Math.pow(1024, digitGroups)) + " " + unitNames[digitGroups];
                }

                sysFileInfo.setFileOriginName(originalFilename);
                sysFileInfo.setFileSuffix(extension);
                sysFileInfo.setFileSizeInfo(fileSizeInfo);
                sysFileInfo.setFileObjectName(fileObjectName);
                sysFileInfo.setFilePath("/profile/upload/" + fileName);
                sysFileInfo.setDelFlag("N");
                sysFileInfo.setCreateBy("admin");
                sysFileInfo.setType("1");
                sysFileInfoService.insertSysFileInfo(sysFileInfo);
                Long fileId = sysFileInfo.getFileId();
                fileIds = fileIds + fileId + ",";
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        CmsAdvertisedDTO dto = new CmsAdvertisedDTO();
        dto.setCategory(category);
        dto.setCountry("USA");
        dto.setLocation(zhouName);
        dto.setCity(city);
        dto.setTitle(title);
        dto.setAge(age);
        dto.setPhone(phone);
        dto.setFullAddress(address);
        dto.setDescription(des);
        dto.setPayment("Cash,");
        dto.setCallType("Incall");
        dto.setViews(views);

        dto.setTopMode(0);
        dto.setTopDays(0);
        dto.setTopMoney(new BigDecimal("0.00"));

        dto.setAutoMode(0);
        dto.setAutoDays(0);
        dto.setAutoMoney(new BigDecimal("0.00"));

        dto.setHighlightMode(0);
        dto.setHighlightDays(0);
        dto.setHighlightMoney(new BigDecimal("0.00"));

        dto.setNormalMode(1);
        dto.setNormalMoney(new BigDecimal("0.00"));

        dto.setFileIds(fileIds);
        dto.setCreateBy("1");
        dto.setCreateTime(new Date());

        dto.setRemark(oriUrl);
        cmsAdvertisedMapper.insert(dto);
        Long finish = System.currentTimeMillis();
        long timeElapsed = finish - start;
        System.out.println("抓取执行时长：" + timeElapsed + " 毫秒");
    }

    private Document getSSLDoc(String url) throws Exception {
        try {
            // 忽略 SSL 验证
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() { return null; }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                    }
            };

            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);

            Document doc = Jsoup.connect(url).timeout(30000).userAgent("").get();
            return doc;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (KeyManagementException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public AjaxResult getOne(CmsAdvertised ca) {
        return AjaxResult.success(cmsAdvertisedMapper.getOne(ca));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insert(CmsAdvertisedDTO dto) {
        try {
            // 当前城市置顶数量是否超过200
            /*int count = cmsAdvertisedMapper.topCount(dto.getCity());
            if (count > 200) {
                return AjaxResult.error("The number of pinned bars in the city is maxed and cannot be pinned");
            }*/
            log.info("request insert cmsAdvertised: --> {} ", JSONUtil.toJsonStr(dto));
            Optional<CmsMode> cmsMode = Optional.ofNullable(iCmsModeService.getCmsMode());
            cmsMode.orElseThrow(() -> new ServiceException("If the billing rules are not defined, contact your administrator"));
            cmsMode.map(CmsMode::getTopMoney)
                    .orElseThrow(() -> new ServiceException("If the top billing is not set, contact the administrator"));
            cmsMode.map(CmsMode::getAutoMoney)
                    .orElseThrow(() -> new ServiceException("Automatic billing is not set, contact your administrator"));
            cmsMode.map(CmsMode::getHighlightMoney)
                    .orElseThrow(() -> new ServiceException("If the highlighted billing is not set, contact the administrator"));
            cmsMode.map(CmsMode::getNormalMoney)
                    .orElseThrow(() -> new ServiceException("If the billing is not set, contact the administrator"));
            // 规则逻辑处理
            Date now = new Date();
            BigDecimal sum = BigDecimal.ZERO;
            // 置顶
            if (1 == dto.getTopMode()) {
                dto.setTopMoney(cmsMode.get().getTopMoney().multiply(new BigDecimal(dto.getTopDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getTopDays(), ChronoUnit.DAYS));
                dto.setTopEndTime(endTime);
                sum = sum.add(dto.getTopMoney());
            }
            // 自动
            if (1 == dto.getAutoMode()) {
                dto.setAutoMoney(cmsMode.get().getAutoMoney().multiply(new BigDecimal(dto.getAutoDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
                dto.setAutoEndTime(endTime);
                sum = sum.add(dto.getAutoMoney());
            }
            // 高亮
            if (1 == dto.getHighlightMode()) {
                dto.setHighlightMoney(cmsMode.get().getHighlightMoney().multiply(new BigDecimal(dto.getHighlightDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
                dto.setHighlightEndTime(endTime);
                sum = sum.add(dto.getHighlightMoney());
            }
            dto.setNormalMoney(cmsMode.get().getNormalMoney());
            dto.setNormalMode(1);
            dto.setCreateTime(now);
            sum = sum.add(dto.getNormalMoney());
            String[] split = dto.getCity().split(",");
            List<String> ads = new ArrayList<>(16);
            Long userId = SecurityUtils.getUserId();
            SysUser sysUser = sysUserMapper.selectUserById(userId);
            sum = sum.multiply(new BigDecimal(split.length));
            if (sysUser.getIntegral().compareTo(sum) < 0) {
                return AjaxResult.error("The balance is insufficient to post");
            }
            for (String city : split) {
                dto.setCity(city).setCreateBy(String.valueOf(userId));
                // 随机插入查看次数
                Random r = new Random();
                Integer views = 300 + (r.nextInt(200));
                dto.setViews(Long.valueOf(views));
                log.info("insert-sj -> {} ", JSONUtil.toJsonStr(dto));
                cmsAdvertisedMapper.insert(dto);
                String address = ruoYiConfig.getDomainNameAddress() + "?id=" + dto.getId();
                ads.add(address);
                // 保存消费记录
                CmsUserAmountLog cua = new CmsUserAmountLog();
                cua.setUserId(userId).setAdId(dto.getId());
                if (1 == dto.getTopMode()) {
                    cua.setConsumeAmount(dto.getTopMoney()).setActionTime(now)
                            .setType("Top")
                            .setRemark("Move Ad to Top of Listings:" + dto.getTopDays() + " days");
                    cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
                }
                if (1 == dto.getAutoMode()) {
                    cua.setConsumeAmount(dto.getAutoMoney()).setActionTime(now)
                            .setType("Auto")
                            .setRemark("Move Ad to Auto of Listings:" + dto.getAutoDays() + " days");
                    cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
                }
                if (1 == dto.getHighlightMode()) {
                    cua.setConsumeAmount(dto.getHighlightMoney()).setActionTime(now)
                            .setType("Highlight")
                            .setRemark("Move Ad to Highlight of Listings:" + dto.getHighlightDays() + " days");
                    cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
                }
                if (1 == dto.getNormalMode()) {
                    cua.setConsumeAmount(dto.getNormalMoney()).setActionTime(now).setType("Normal");
                    cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
                }
            }
            // 更新余额
            BigDecimal subtract = sysUser.getIntegral().subtract(sum);
            SysUser su = new SysUser();
            su.setUserId(userId);
            su.setIntegral(subtract);
            sysUserMapper.updateUserIntegral(su);
            return AjaxResult.success("", ads);
        } catch (Exception e) {
            log.error("异常信息", e);
            throw new ServiceException("The service is abnormal");
        }
    }



    @Override
    public AjaxResult update(CmsAdvertisedDTO dto) {
        try {
            Optional<CmsMode> cmsMode = Optional.ofNullable(iCmsModeService.getCmsMode());
            cmsMode.orElseThrow(() -> new ServiceException("If the billing rules are not defined, contact your administrator"));
            cmsMode.map(CmsMode::getTopMoney)
                    .orElseThrow(() -> new ServiceException("If the top billing is not set, contact the administrator"));
            cmsMode.map(CmsMode::getAutoMoney)
                    .orElseThrow(() -> new ServiceException("Automatic billing is not set, contact your administrator"));
            cmsMode.map(CmsMode::getHighlightMoney)
                    .orElseThrow(() -> new ServiceException("If the highlighted billing is not set, contact the administrator"));
            cmsMode.map(CmsMode::getNormalMoney)
                    .orElseThrow(() -> new ServiceException("If the billing is not set, contact the administrator"));
            Date now = new Date();
            BigDecimal sum = BigDecimal.ZERO;
            String[] split = dto.getCity().split(",");
            // 置顶
            if (1 == dto.getTopMode()) {
                dto.setTopMoney(cmsMode.get().getTopMoney().multiply(new BigDecimal(dto.getTopDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getTopDays(), ChronoUnit.DAYS));
                dto.setTopEndTime(endTime);
                sum = sum.add(dto.getTopMoney());
            }
            // 自动
            if (1 == dto.getAutoMode()) {
                dto.setAutoMoney(cmsMode.get().getAutoMoney().multiply(new BigDecimal(dto.getAutoDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
                dto.setAutoEndTime(endTime);
                sum = sum.add(dto.getAutoMoney());
            }
            // 高亮
            if (1 == dto.getHighlightMode()) {
                dto.setHighlightMoney(cmsMode.get().getHighlightMoney().multiply(new BigDecimal(dto.getHighlightDays())));
                Date endTime = Date.from(now.toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
                dto.setHighlightEndTime(endTime);
                sum = sum.add(dto.getHighlightMoney());
            }
            List<String> ads = new ArrayList<>(16);
            Long userId = SecurityUtils.getUserId();
            SysUser sysUser = sysUserMapper.selectUserById(userId);
            sum = sum.multiply(new BigDecimal(split.length));
            if (sysUser.getIntegral().compareTo(sum) < 0) {
                return AjaxResult.error("The balance is insufficient to post");
            }
            Arrays.stream(split)
                    .forEach(c -> {
                        CmsAdvertised ca = cmsAdvertisedMapper.getById(dto.getId());
                        if (null != ca) {
                            dto.setUpdateTime(new Date());
                            dto.setNormalMode(1);
                            if (0 == dto.getTopMode()) {
                                dto.setTopMode(ca.getTopMode());
                            }
                            if (0 == dto.getAutoMode()) {
                                dto.setAutoMode(ca.getAutoMode());
                            }
                            if (0 == dto.getHighlightMode()) {
                                dto.setHighlightMode(ca.getHighlightMode());
                            }
                            if (1 == dto.getTopMode() || 1 == dto.getAutoMode() || 1 == dto.getHighlightMode()) {
                                // 处理时间
                                processingTime(dto, ca, now);
                                // 更新
                                cmsAdvertisedMapper.update(dto);
                                saveXf(dto, userId, now);
                            } else {
                                dto.setTopMode(ca.getTopMode())
                                        .setAutoMode(ca.getAutoMode())
                                        .setHighlightMode(ca.getHighlightMode());
                                cmsAdvertisedMapper.update(dto);
                            }
                            String address = ruoYiConfig.getDomainNameAddress() + "?id=" + dto.getId();
                            ads.add(address);
                        } /*else {
                            // 新增
                            dto.setCity(c).setCreateBy(String.valueOf(userId));
                            cmsAdvertisedMapper.insert(dto);
                            String address = ruoYiConfig.getDomainNameAddress() + "?id=" + dto.getId();
                            ads.add(address);
                            // 保存消费记录
                            saveXf(dto, userId, now);
                        }*/
                    });
            // 更新余额
            BigDecimal subtract = sysUser.getIntegral().subtract(sum);
            SysUser su = new SysUser();
            su.setUserId(userId);
            su.setIntegral(subtract);
            sysUserMapper.updateUserIntegral(su);
            return AjaxResult.success("", ads);
        } catch (Exception e) {
            throw new ServiceException("The service is abnormal");
        }
    }

    private void processingTime(CmsAdvertisedDTO dto, CmsAdvertised ca, Date now) {
        /*// 处理三种模式的通用方法
        BiFunction<Date, Integer, Date> calculateEndTime = (currentEndTime, daysToAdd) -> {
            Date baseTime = currentEndTime.after(now) ? now : currentEndTime;
            return Date.from(baseTime.toInstant().plus(daysToAdd, ChronoUnit.DAYS));
        };
        // 置顶模式
        if (1 == dto.getTopMode()) {
            dto.setTopEndTime(calculateEndTime.apply(ca.getTopEndTime(), dto.getTopDays()));
        }

        // 自动模式
        if (1 == dto.getAutoMode()) {
            dto.setAutoEndTime(calculateEndTime.apply(ca.getAutoEndTime(), dto.getAutoDays()));
        }

        // 高亮模式
        if (1 == dto.getHighlightMode()) {
            dto.setHighlightEndTime(calculateEndTime.apply(ca.getHighlightEndTime(), dto.getHighlightDays()));
        }*/
        if (1 == dto.getTopMode()) {
            Date endTime;
            if (ca.getTopEndTime().after(now)) {
                endTime = Date.from(now.toInstant().plus(dto.getTopDays(), ChronoUnit.DAYS));
            } else {
                endTime = Date.from(ca.getTopEndTime().toInstant().plus(dto.getTopDays(), ChronoUnit.DAYS));
            }
            dto.setTopEndTime(endTime);
        }
        // 自动
        if (1 == dto.getAutoMode()) {
            Date endTime;
            if (ca.getAutoEndTime().after(now)) {
                endTime = Date.from(now.toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
            } else {
                endTime = Date.from(ca.getTopEndTime().toInstant().plus(dto.getAutoDays(), ChronoUnit.DAYS));
            }
            dto.setAutoEndTime(endTime);
        }
        // 高亮
        if (1 == dto.getHighlightMode()) {
            Date endTime;
            if (ca.getHighlightEndTime().after(now)) {
                endTime = Date.from(now.toInstant().plus(dto.getHighlightDays(), ChronoUnit.DAYS));
            } else {
                endTime = Date.from(ca.getTopEndTime().toInstant().plus(dto.getHighlightDays(), ChronoUnit.DAYS));
            }
            dto.setHighlightEndTime(endTime);
        }
    }

    private void saveXf(CmsAdvertisedDTO dto, Long userId, Date now) {
        CmsUserAmountLog cua = new CmsUserAmountLog();
        cua.setUserId(userId).setAdId(dto.getId());
        if (1 == dto.getTopMode()) {
            cua.setConsumeAmount(dto.getTopMoney()).setActionTime(now)
                    .setType("Top")
                    .setRemark("Move Ad to Top of Listings:" + dto.getTopDays() + " days");
            cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
        }
        if (1 == dto.getAutoMode()) {
            cua.setConsumeAmount(dto.getAutoMoney()).setActionTime(now)
                    .setType("Auto")
                    .setRemark("Move Ad to Auto of Listings:" + dto.getAutoDays() + " days");
            cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
        }
        if (1 == dto.getHighlightMode()) {
            cua.setConsumeAmount(dto.getHighlightMoney()).setActionTime(now)
                    .setType("Highlight")
                    .setRemark("Move Ad to Highlight of Listings:" + dto.getHighlightDays() + " days");
            cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
        }
        /*if (1 == dto.getNormalMode()) {
            cua.setConsumeAmount(dto.getNormalMoney()).setActionTime(now);
            cmsUserAmountLogMapper.insertCmsUserAmountLog(cua);
        }*/
    }

    @Override
    public AjaxResult delete(Long id) {
        return AjaxResult.success(cmsAdvertisedMapper.delete(id));
    }
}
